package net.hanjava.picbox;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import net.hanjava.cache.Cache;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import android.util.Log;

/**
 * 'content://net.hanjava.picbot.zoom/?src=encodedurl&ratio=0.7'
 * 
 * @author behumble
 */
public class ZoomProvider extends ContentProvider {
	private static final String TAG = "ZoomProvider";
	public static final String AUTHORITY = "net.hanjava.picbot.zoom";
	public static final String PARAM_SRC_URI = "src";
	public static final String PARAM_RATIO = "ratio";

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		throw new RuntimeException("Do not call me");
	}

	@Override
	public String getType(Uri uri) {
		throw new RuntimeException("Do not call me");
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		throw new RuntimeException("Do not call me");
	}

	@Override
	public boolean onCreate() {
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		throw new RuntimeException("Do not call me");
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		throw new RuntimeException("Do not call me");
	}

	@Override
	public ParcelFileDescriptor openFile(Uri uri, String mode)
			throws FileNotFoundException {
		long before = System.currentTimeMillis();

		// extract parameters
		String srcUrl = uri.getQueryParameter(PARAM_SRC_URI);
		Uri srcUriObj = Uri.parse(srcUrl);
		String ratio = uri.getQueryParameter(PARAM_RATIO);

		File validCacheFile = getValidCache(srcUriObj, ratio);
		if (!validCacheFile.exists()) {
			validCacheFile = createZoomedPicture(srcUrl, ratio, validCacheFile);
		}

		if(Log.isLoggable(TAG, Log.INFO)) {
			long after = System.currentTimeMillis();
			Log.i(TAG, "Time To [load original image -> create scaled image] : "+(after-before));
		}

		ParcelFileDescriptor result = ParcelFileDescriptor.open(validCacheFile,
				ParcelFileDescriptor.MODE_READ_ONLY);
		return result;
	}

	private File getValidCache(Uri srcUri, String ratio) {
		// CACHE_BASE + source path + authority + ratio + ".png"
		// '/sdcard/.hanjava/file/sdcard/images/1.jpg/net.hanjava.picbot.zoom/0.4.png'
		StringBuilder pathBuf = new StringBuilder(Cache.CACHE_DIR);
		pathBuf.append(srcUri.getScheme());
		pathBuf.append('/');
		pathBuf.append(srcUri.getSchemeSpecificPart());
		pathBuf.append('/');
		pathBuf.append(AUTHORITY);
		pathBuf.append('/');
		pathBuf.append(ratio);
		pathBuf.append(".png");
		File file = new File(pathBuf.toString());
		if(Log.isLoggable(TAG, Log.INFO)) {
			Log.i(TAG, "getValidCache() - "+file.getAbsolutePath());
		}
		return file;
	}

	private File createZoomedPicture(String srcUrl, String ratio, File outFile) {
		Uri srcUriObj = Uri.parse(srcUrl);
		ContentResolver cr = getContext().getContentResolver();
		int orgWidth = -1;
		int orgHeight = -1;
		Bitmap resizedBM = null;
		try {
			InputStream is = cr.openInputStream(srcUriObj);
			Bitmap orgBitmap = BitmapFactory.decodeStream(is, null, null);
			is.close();
			orgWidth = orgBitmap.getWidth();
			orgHeight = orgBitmap.getHeight();
			double dRatio = Double.parseDouble(ratio);
			int newWidth = (int)(orgWidth * dRatio);
			int newHeight = (int)(orgHeight * dRatio);
			resizedBM  = orgBitmap.createScaledBitmap(orgBitmap, newWidth, newHeight, false);
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		}

		if (resizedBM == null)
			throw new RuntimeException("Failed to decode a image");


		try {
			File dir = outFile.getParentFile();
			if(!dir.exists()) {
				dir.mkdirs();
			}

			BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(outFile), 1024 );
			resizedBM.compress(CompressFormat.PNG, 0, bos);
			bos.close();
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		}
		return outFile;
	}
}